package com.book.common.util;

import com.alibaba.fastjson.JSONArray;
import com.book.common.entity.Browser;
import com.book.common.lang.Tuple2;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URLEncoder;
import java.util.Locale;
import java.util.Optional;

/**
 * Description：
 *
 * @Author： leo.xiong
 * @CreateDate： 2020/04/25 14:25
 * @Email： leo.xiong@suyun360.com
 * Version：1.0
 */
@Slf4j
public class GoogleTranslateUtil {
    private static final String PATH = "/gettk.js";
    public static final int MAX_MAP_SIZE = 3000;
    static ScriptEngine engine = null;

    private Browser browser = null;

    public static final String UTF_8 = "UTF-8";

    private static GoogleTranslateUtil GOOGLE_TRANSLATE_UTIL;

    static {
        ScriptEngineManager maneger = new ScriptEngineManager();
        engine = maneger.getEngineByName("javascript");
        FileInputStream fileInputStream = null;
        Reader scriptReader = null;
        try {
            scriptReader = new InputStreamReader(GoogleTranslateUtil.class.getResourceAsStream(PATH), UTF_8);
            engine.eval(scriptReader);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (scriptReader != null) {
                try {
                    scriptReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static GoogleTranslateUtil getInstance(String ip, Integer port) {
        if (GOOGLE_TRANSLATE_UTIL == null) {
            synchronized (GoogleTranslateUtil.class) {
                if (GOOGLE_TRANSLATE_UTIL == null) {
                    GOOGLE_TRANSLATE_UTIL = new GoogleTranslateUtil(ip, port);
                }
            }
        }
        return GOOGLE_TRANSLATE_UTIL;
    }

    private GoogleTranslateUtil(String ip, Integer port) {
        this.browser = new Browser();
        if (StringUtils.isNotEmpty(ip) && port != null) {
            this.browser.setProxy(ip, port);
        }
    }

    private final String getTKK() {
        browser.setUrl("https://translate.google.cn/");
        try {
            String result = browser.executeGet();
            if (StringUtils.isNotBlank(result)) {
                if (result.indexOf("tkk") > -1) {
                    String matchString = RegularUtil.findMatchString(result, "tkk:.*?',");
                    String tkk = matchString.substring(5, matchString.length() - 2);
                    return tkk;
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("获取 tkk 出错");
        }
        return null;
    }

    private static final String getTK(String value, String tkk) {
        String result = null;
        try {
            if (engine instanceof Invocable) {
                Invocable invocable = (Invocable) engine;
                result = (String) invocable.invokeFunction("tk", new Object[]{value, tkk});
            }
        } catch (Exception e) {
            throw new RuntimeException("获取 tk 出错");
        }
        return result;
    }

    private final String translate(String value, String from, String languageAndCountry) {
        if (StringUtils.isEmpty(value)) {
            return null;
        }
        String tkk = getTKK();
        if (StringUtils.isBlank(tkk)) {
            throw new RuntimeException("无法获取 tkk");
        }
        String tk = getTK(value, tkk);
        try {
            value = URLEncoder.encode(value, UTF_8);
        } catch (Exception e) {
            e.printStackTrace();
        }

        StringBuffer buffer = new StringBuffer("https://translate.google.cn/translate_a/single?client=t");

        if (StringUtils.isBlank(from)) {
            from = "auto";
        }
        buffer.append("&sl=" + from);
        buffer.append("&tl=" + languageAndCountry);
        buffer.append("&hl=zh-CN&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&ie=UTF-8&oe=UTF-8&source=btn&kc=0");
        buffer.append("&tk=" + tk);
        buffer.append("&q=" + value);
        browser.setUrl(buffer.toString());
        try {
            String result = browser.executeGet();
            JSONArray array = (JSONArray) JSONArray.parse(result);
            JSONArray rArray = array.getJSONArray(0);
            StringBuffer rBuffer = new StringBuffer();
            for (int i = 0; i < rArray.size(); i++) {
                String r = rArray.getJSONArray(i).getString(0);
                if (StringUtils.isNotBlank(r)) {
                    rBuffer.append(r);
                }
            }
            return rBuffer.toString();
        } catch (Exception e) {
            throw new RuntimeException("结果集解析出错");
        }
    }

    /**
     * 根据传入的国别语言对象获取转换信息
     *
     * @param locale
     * @param value
     * @return
     */

    public static String translate(Locale locale, String value) {
        return translate(locale, null, value, null);
    }

    public static String translate(Locale locale, String key, String value, String defaultValue) {
        return translate(locale, key, value, null, null, defaultValue);
    }

    /**
     * 项目默认使用中文-简体，没有国家使用中文-简体
     *
     * @param locale
     * @param value
     * @param ip
     * @param port
     * @return
     */
    public static String translate(Locale locale, String key, String value, String ip, Integer port, String defaultValue) {
        String message = null;
        try {
            if (StringUtils.isEmpty(value)) {
                return value;
            }
            key = Optional.ofNullable(key).orElse(getKey(value));
            message = GuavaCacheUtil.get(locale.getLanguage() + "_" + locale.getCountry(), key, String.class);
            if (message != null) {
                return message;
            }
            message = getInstance(ip, port).translate(value, null, locale.getLanguage() + "_" + locale.getCountry().toLowerCase());
        } catch (Exception e) {
            log.warn("翻译出错", e);
            message = Optional.ofNullable(defaultValue).orElse(value);
        }
        /**
         * 缓存保留3天
         */
        GuavaCacheUtil.put(locale.getLanguage() + "_" + locale.getCountry(), key, message, 259200L);
        return message;
    }

    public static String getKey(String key) {
        StringBuilder stringBuilder = new StringBuilder();
        char[] c = key.toCharArray();
        for (int i = 0; i < c.length; i++) {
            stringBuilder.append(Integer.toHexString(c[i]));
        }
        return stringBuilder.toString();
    }
}
